"""
Grave! Important! Важно!

Proletoj el ĉiuj landoj, unuiĝu!
Workers of the world, unite!
Пролетарии всех стран, соединяйтесь!

https://tkom.pro
"""

from rest_framework import generics, viewsets, views, mixins
from rest_framework.exceptions import NotFound
from django.db.models import F, Q, Value, Count, Sum, Case, When, IntegerField, BooleanField
from .serializers import *
from muroj.models import *
from itertools import chain


class MurojEnskribojView(viewsets.ReadOnlyModelViewSet):
    serializer_class = MurojEnskriboSerializer
    lookup_field = 'uuid'

    @staticmethod
    def make_query(queryset, avataro, avataro_min, kovrilo, interesoj_tuta, mia_interese):
        return (queryset.objects
                .select_related('posedanto')
                .annotate(nomo=F('posedanto__nomo__enhavo'),
                          kovrilo_bildo=kovrilo,
                          avataro_bildo=avataro,
                          avataro_bildo_min=avataro_min,
                          interesoj_tuta=Count(Case(
                              When(interesoj_tuta, then=Value(1)),
                              default=Value(None), output_field=IntegerField())),
                          mia_interese=Count(Case(
                              When(mia_interese, then=Value(1)),
                              default=Value(None), output_field=BooleanField())),
                          komentoj_tuta=Value(0, output_field=IntegerField()))
                .filter(forigo=False, arkivo=False)
                .order_by('-krea_dato'))

    def __get_models(self):
        """
        Метод выдает словарь с классами Моделей и словарями запросов для них
        """
        # Получаем текущего пользователя
        uzanto_id = self.request.user.id if self.request.user.is_authenticated else -1

        # Список моделей, по которым ведётся поиск
        return {MurojSociaprojektoEnskribo: {
                'kovrilo': F('posedanto__komunumojsociaprojektokovrilo__bildo'),
                'avataro': F('posedanto__komunumojsociaprojektoavataro__bildo'),
                'avataro_min': F('posedanto__komunumojsociaprojektoavataro__bildo_min'),
                'interesoj_tuta': Q(murojsociaprojektoenskribointerese__forigo=False),
                'mia_interese': Q(murojsociaprojektoenskribointerese__forigo=False,
                              murojsociaprojektoenskribointerese__autoro_id=uzanto_id)},
            MurojSovetoEnskribo: {
                'kovrilo': F('posedanto__komunumojsovetokovrilo__bildo'),
                'avataro': F('posedanto__komunumojsovetoavataro__bildo'),
                'avataro_min': F('posedanto__komunumojsovetoavataro__bildo_min'),
                'interesoj_tuta': Q(murojsovetoenskribointerese__forigo=False),
                'mia_interese': Q(murojsovetoenskribointerese__forigo=False,
                                  murojsovetoenskribointerese__autoro_id=uzanto_id)},
            MurojGrupoEnskribo: {
                'kovrilo': F('posedanto__komunumojgrupokovrilo__bildo'),
                'avataro': F('posedanto__komunumojgrupoavataro__bildo'),
                'avataro_min': F('posedanto__komunumojgrupoavataro__bildo_min'),
                'interesoj_tuta': Q(murojgrupoenskribointerese__forigo=False),
                'mia_interese': Q(murojgrupoenskribointerese__forigo=False,
                                  murojgrupoenskribointerese__autoro_id=uzanto_id)},
            MurojOrganizoEnskribo: {
                'kovrilo': F('posedanto__komunumojorganizokovrilo__bildo'),
                'avataro': F('posedanto__komunumojorganizoavataro__bildo'),
                'avataro_min': F('posedanto__komunumojorganizoavataro__bildo_min'),
                'interesoj_tuta': Q(murojorganizoenskribointerese__forigo=False),
                'mia_interese': Q(murojorganizoenskribointerese__forigo=False,
                                  murojorganizoenskribointerese__autoro_id=uzanto_id)}
        }

    def __get_queryset(self, uuid):
        filter = []
        posedanto_id = self.kwargs.get('komunumo_uuid', None)

        if uuid is not None:
            filter.append(Q(uuid=uuid))

        if posedanto_id is not None:
            filter.append(Q(posedanto_id=posedanto_id))

        for model, model_dict in self.__get_models().items():
            result = self.make_query(model, **model_dict).filter(*filter)

            if result.count():
                return result

        raise NotFound

    def get_queryset(self):
        if self.lookup_field in self.kwargs or 'komunumo_uuid' in self.kwargs:
            # Если требуется конкретная запись
            queryset = self.__get_queryset(self.kwargs.get(self.lookup_field))
        else:
            queryset = list()

            for model, model_dict in self.__get_models().items():
                result = self.make_query(model, **model_dict)
                queryset.extend(result)

            queryset.sort(key=lambda x: x.krea_dato, reverse=True)

        return queryset

class MurojKomentojView(viewsets.ReadOnlyModelViewSet):
    serializer_class = MurojEnskriboKomentoSerializer
    lookup_field = 'uuid'

    @staticmethod
    def make_query(queryset):
        return queryset.objects.filter(forigo=False, arkivo=False).order_by('-krea_dato')

    @staticmethod
    def get_models():
        return (
            MurojSociaprojektoEnskriboKomento,
            MurojSovetoEnskriboKomento,
            MurojOrganizoEnskriboKomento,
            MurojGrupoEnskriboKomento,
        )

    def __get_queryset(self, uuid):
        filter = []
        enskribo_id = self.kwargs.get('enskribo_uuid')

        if uuid is not None:
            filter.append(Q(uuid=uuid))

        if enskribo_id is not None:
            filter.append(Q(posedanto_id=enskribo_id))

        for model in self.get_models():
            queryset = self.make_query(model).filter(*filter)

            if queryset.count():
                return queryset

        raise NotFound

    def get_queryset(self):
        if self.lookup_field in self.kwargs or 'enskribo_uuid' in self.kwargs:
            # Если требуется конкретная запись
            queryset = self.__get_queryset(self.kwargs.get(self.lookup_field))
        else:
            queryset = list()

            for model in self.get_models():
                result = self.make_query(model)
                queryset.extend(result)

            queryset.sort(key=lambda x: x.krea_dato, reverse=True)

        return queryset